package com.quan.mall.service.impl;
import java.math.BigDecimal;
import java.time.LocalDateTime;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.binarywang.wxpay.bean.entpay.EntPayRequest;
import com.github.binarywang.wxpay.bean.entpay.EntPayResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.quan.commons.core.bean.R;
import com.quan.commons.core.biz.support.MyBaseServiceImpl;
import com.quan.commons.core.configuration.WxPayConfiguration;
import com.quan.commons.core.utils.*;
import com.quan.commons.tools.sms.ALiYunSMSTools;
import com.quan.mall.commons.vo.UmsMemberVo;
import com.quan.mall.entity.FmsMemberCashFlow;
import com.quan.mall.entity.FmsMemberWallet;
import com.quan.mall.entity.UmsMember;
import com.quan.mall.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.quan.mall.commons.vo.FmsMemberWithdrawVo;
import com.quan.mall.entity.FmsMemberWithdraw;
import com.quan.mall.mapper.FmsMemberWithdrawMapper;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;


@Slf4j
@Service
public class FmsMemberWithdrawServiceImpl extends MyBaseServiceImpl<FmsMemberWithdrawMapper, FmsMemberWithdraw> implements FmsMemberWithdrawService {

    @Autowired
	private FmsMemberWithdrawMapper mapper;

    @Autowired
    private UmsMemberService umsMemberService;

    @Autowired
    private FmsMemberWalletService fmsMemberWalletService;

    @Autowired
    private FmsFinanceCashFlowService fmsFinanceCashFlowService;

    @Autowired
    private FmsMemberCommisionFreezeService fmsMemberCommisionFreezeService;

    @Autowired
    private FmsMemberCashFlowService fmsMemberCashFlowService;

	@Override
    public List<FmsMemberWithdrawVo> queryList(PageUtils pageUtils, FmsMemberWithdrawVo vo) {
        QueryWrapper<FmsMemberWithdraw> queryWrapper = new QueryWrapper<FmsMemberWithdraw>(vo);

        List<FmsMemberWithdraw> list = super.list(pageUtils, queryWrapper);
        List<FmsMemberWithdrawVo> collect = list.stream().map(item -> {
            FmsMemberWithdrawVo bean = new FmsMemberWithdrawVo();
            BeanUtils.copyProperties(item, bean);
            return bean;
        }).collect(Collectors.toList());

        return collect;
    }

    @Override
    public PageUtils queryPage(PageUtils pageUtils, FmsMemberWithdrawVo vo) {
        QueryWrapper<FmsMemberWithdraw> queryWrapper = new QueryWrapper<FmsMemberWithdraw>(vo);

        if(StringUtils.isNotBlank(vo.getKeyword())) {
            queryWrapper.and(w -> {
                w.like("name", vo.getKeyword());
            });
        }

        // 时间选择->0:今天;1:昨天;2:最近7天;3:最近30天:4:本月;5本年
        if (null != vo.getDateAttr()) {
            if (vo.getDateAttr() == 0) {
                queryWrapper.apply("date_format(ctime, '%Y-%m-%d') >= {0}", LocalDate.now());
            } else if (vo.getDateAttr() == 1) {
                queryWrapper.apply("date_format(ctime, '%Y-%m-%d') >= {0}", LocalDate.now().plusDays(-1));
            } else if (vo.getDateAttr() == 2) {
                queryWrapper.apply("date_format(ctime, '%Y-%m-%d') >= {0} and date_format(ctime, '%Y-%m-%d') <= {1}", LocalDate.now().plusDays(-7), LocalDate.now());
            } else if (vo.getDateAttr() == 3) {
                queryWrapper.apply("date_format(ctime, '%Y-%m-%d') >= {0} and date_format(ctime, '%Y-%m-%d') <= {1}", LocalDate.now().plusDays(-30), LocalDate.now());
            } else if (vo.getDateAttr() == 4) {
                // 本月的第一天
                final LocalDate firstMonthDay = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
                // 本月的最后一天
                final LocalDate lastMonthDay = LocalDate.now().plusYears(1).with(TemporalAdjusters.firstDayOfMonth());
                queryWrapper.apply("date_format(ctime, '%Y-%m-%d') >= {0} and date_format(ctime, '%Y-%m-%d') <= {1}", firstMonthDay, lastMonthDay);
            } else if (vo.getDateAttr() == 5) {
                // 今年的第一天
                final LocalDate firstYearDay = LocalDate.now().with(TemporalAdjusters.firstDayOfYear());
                // 今年的最后一天
                final LocalDate lastYearDay = LocalDate.now().plusYears(1).with(TemporalAdjusters.firstDayOfYear());
                queryWrapper.apply("date_format(ctime, '%Y-%m-%d') >= {0} and date_format(ctime, '%Y-%m-%d') <= {1}", firstYearDay, lastYearDay);
            }
        } else {
            // 下单日期范围
            if (StringUtils.isNotEmpty(vo.getDateRange())) {
                final String[] split = vo.getDateRange().split(",");
                String startDate = split[0];
                String endDate = split[1];
                queryWrapper.apply("date_format(ctime, '%Y-%m-%d') >= {0} and date_format(ctime, '%Y-%m-%d') <= {1}", startDate, endDate);
            }
        }


        final IPage<FmsMemberWithdraw> page = super.selectPage(pageUtils, queryWrapper);

        PageUtils ps = new PageUtils(page);

        final List<FmsMemberWithdraw> records = page.getRecords();

        final List<FmsMemberWithdraw> collect = records.stream().map((item) -> {
            FmsMemberWithdrawVo bean = new FmsMemberWithdrawVo();
            BeanUtils.copyProperties(item, bean);
            return bean;
        }).collect(Collectors.toList());

        ps.setRecords(collect);
        return ps;
    }

    @Transactional
    @Override
    public R apply(FmsMemberWithdrawVo vo) {

	    // 申请提现会员
        final UmsMember member = this.umsMemberService.getById(vo.getMemberId());

        // 会员的钱包
        final UmsMemberVo myWallter = this.umsMemberService.getMyWallter(vo.getMemberId());

        if(vo.getApplyTakeAmount().compareTo(myWallter.getAmount()) > 1) {
            return R.failure("申请提现失败：余额不足");
        }

        FmsMemberWithdraw withdraw = new FmsMemberWithdraw();
        withdraw.setAppId(vo.getAppId());
        withdraw.setOpenid(member.getOpenid());
        withdraw.setMemberId(member.getId());
        withdraw.setName(member.getNickname());
        withdraw.setPhone(member.getMobile());
        withdraw.setTakeAmount(myWallter.getAmount());
        withdraw.setApplyTakeAmount(vo.getApplyTakeAmount());
        withdraw.setTakeAmountStatus(1);

        super.save(withdraw);

        // 扣减钱包余额
        FmsMemberWallet wallet = this.fmsMemberWalletService.getMemberWallter(vo.getMemberId());
        wallet.setAmount(myWallter.getAmount().multiply(vo.getApplyTakeAmount()));
        this.fmsMemberWalletService.updateById(wallet);

        return R.ok();
    }

    @Transactional
    @Override
    public R agree(FmsMemberWithdrawVo vo, HttpServletRequest request) {

        FmsMemberWithdraw withdraw = super.getById(vo.getId());
        withdraw.setCommissionPercent(vo.getCommissionPercent());
        withdraw.setCommissionAmount(vo.getCommissionAmount());
        withdraw.setFactTakeAmount(vo.getFactTakeAmount());


        // 同意申请，开始微信转账
        if(StringUtils.isNotBlank(withdraw.getOpenid())) {

            EntPayRequest entPayRequest = new EntPayRequest();
            entPayRequest.setPartnerTradeNo(OrderUtils.getSN());
            entPayRequest.setOpenid(withdraw.getOpenid());
            entPayRequest.setCheckName("FORCE_CHECK");
            entPayRequest.setReUserName(withdraw.getName());
            entPayRequest.setAmount(AmountUtils.changeY2F(withdraw.getFactTakeAmount()));
            entPayRequest.setDescription("佣金提现["+withdraw.getMemberId()+"]");
            entPayRequest.setSpbillCreateIp(IpHelper.getIpAddr(request));

            final WxPayService wxPayService = WxPayConfiguration.getPayService(withdraw.getAppId());
            try {
                EntPayResult entPayResult = wxPayService.getEntPayService().entPay(entPayRequest);
                if(entPayResult.getResultCode().equals("SUCCESS")) {
                    // 企业付款成功
                    if(entPayResult.getResultCode().equals("SUCCESS") && entPayResult.getReturnCode().equals("SUCCESS")) {

                        // 会员提现，并转账成功：微信转账（申请审核通过）
                        withdraw.setTakeAmountStatus(3);
                        // 企业付款成功，返回的微信付款单号
                        withdraw.setPaymentNo(entPayResult.getPaymentNo());
                        withdraw.setPaymentTime(entPayResult.getPaymentTime());

                    } else {
                        // 微信转账失败
                        withdraw.setTakeAmountStatus(4);
                        // 企业付款失败
                        log.error("企业付款失败，错误码：{}，错误代码描述：{}", entPayResult.getErrCode(), entPayResult.getErrCodeDes());
                        return R.failure("转账失败["+entPayResult.getErrCodeDes()+"]");
                    }
                } else {
                    // 微信转账失败
                    withdraw.setTakeAmountStatus(4);
                    // 企业付款失败
                    log.error("企业付款失败，错误码：{}，错误代码描述：{}", entPayResult.getErrCode(), entPayResult.getErrCodeDes());
                    return R.failure("转账失败["+entPayResult.getErrCodeDes()+"]");
                }
            } catch (WxPayException e) {
                e.printStackTrace();
            }

            super.updateById(withdraw);

            // 申请提现会员
            final UmsMember member = this.umsMemberService.getById(withdraw.getMemberId());

            // 将申请提现记录到会员交易流水表中
            FmsMemberCashFlow cashFlow = new FmsMemberCashFlow();
            cashFlow.setOpenId(member.getOpenid());
            cashFlow.setMemberId(member.getId());
            cashFlow.setMemberName(member.getNickname());

            cashFlow.setTransactionAmount(vo.getFactTakeAmount());
            cashFlow.setTransactionType(3);
            cashFlow.setRemarks("会员申请提现->申请金额：["+vo.getApplyTakeAmount()+"]，手续费：["+vo.getCommissionPercent()+"]，实际提现金额：["+vo.getFactTakeAmount()+"]");

            this.fmsMemberCashFlowService.save(cashFlow);
        } else {
            return R.failure("转账失败：会员未绑定微信，无法完成转账");
        }

        return R.ok();
    }

    @Transactional
    @Override
    public R reject(FmsMemberWithdrawVo vo) {
        FmsMemberWithdraw withdraw = super.getById(vo.getId());
        withdraw.setTakeAmountStatus(2);
        withdraw.setRemarks(vo.getRemarks());

        super.updateById(withdraw);

        // 申请提现会员
        final UmsMember member = this.umsMemberService.getById(withdraw.getMemberId());

        // 将申请的提现金额加回到钱包余额
        FmsMemberWallet wallet = this.fmsMemberWalletService.getMemberWallter(member.getId());
        wallet.setAmount(wallet.getAmount().add(withdraw.getApplyTakeAmount()));
        this.fmsMemberWalletService.updateById(wallet);

        return R.ok();
    }
}